#include "stdafx.h"
#include "USMDLoader.h"
#include "UModel.h"
#include "UFace.h"
#include "UTextureManager.h"
#include <iostream>
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <algorithm>
#include <cctype>
#include <string>

using namespace std;

GLfloat stringtof(string& str) {
	return (GLfloat)(atof(str.c_str()));
}

vector<TTriangle >* loadTriangleBlock(ifstream& ifs) {
	string str = "";
	vector<TTriangle>* triangleList = new vector<TTriangle>();
	vector<string> values;
	TTriangle triangle;
	getline(ifs, str);
	while(!ifs.eof() && str.compare(0, 3, "end")) {
		if( *--str.end() == '\r' ) str.erase(--str.end()); //Filenames don't generally have these in them
//		triangle.texture = GTextureManager->getTexture(str);

		getline(ifs, str); transform (str.begin(),str.end(), str.begin(), ::tolower);
		boost::split(values, str, boost::is_any_of(" "));
		if(values.size()>=9) {
			vector<GLfloat > flts;
			transform(values.begin(), values.end(), back_inserter(flts), &stringtof);
			triangle.v1.x = flts[1];
			triangle.v1.y = flts[2];
			triangle.v1.z = flts[3];
			triangle.n1.x = flts[4];
			triangle.n1.y = flts[5];
			triangle.n1.z = flts[6];
			triangle.uv1.x = flts[7];
			triangle.uv1.y = flts[8];
		}

		getline(ifs, str); transform (str.begin(),str.end(), str.begin(), ::tolower);
		boost::split(values, str, boost::is_any_of(" "));
		if(values.size()>=9) {
			vector<GLfloat > flts;
			transform(values.begin(), values.end(), back_inserter(flts), &stringtof);
			triangle.v2.x = flts[1];
			triangle.v2.y = flts[2];
			triangle.v2.z = flts[3];
			triangle.n2.x = flts[4];
			triangle.n2.y = flts[5];
			triangle.n2.z = flts[6];
			triangle.uv2.x = flts[7];
			triangle.uv2.y = flts[8];
		}

		getline(ifs, str); transform (str.begin(),str.end(), str.begin(), ::tolower);
		boost::split(values, str, boost::is_any_of(" "));
		if(values.size()>=9) {
			vector<GLfloat > flts;
			transform(values.begin(), values.end(), back_inserter(flts), &stringtof);
			triangle.v3.x = flts[1];
			triangle.v3.y = flts[2];
			triangle.v3.z = flts[3];
			triangle.n3.x = flts[4];
			triangle.n3.y = flts[5];
			triangle.n3.z = flts[6];
			triangle.uv3.x = flts[7];
			triangle.uv3.y = flts[8];
		}

/*
		//FIXME: Surface normals are not correct? [HAX]
		TVector n;
		n=((triangle.v1-triangle.v2)*(triangle.v3-triangle.v2));
		n.Normalize();
		triangle.n1 = n;
		triangle.n2 = n;
		triangle.n3 = n;
// 		triangle.n1.Normalize();
// 		triangle.n2.Normalize();
// 		triangle.n3.Normalize();
*/

		triangleList->push_back(triangle);
		values.clear();
		getline(ifs, str);
	}
	return triangleList;
}

TModel* TSMDLoader::loadModelFromStream(ifstream& ifs) {
	if(ifs == NULL) {
		fprintf(stderr, "Error: can not read from null stream!");
		return new TModel();
	}
	TModel* model = new TModel();
	string str;
	getline(ifs, str); transform (str.begin(),str.end(), str.begin(), ::tolower);

	// 0x0d 0x0a windows line endings leave an 0x0d char in linux
	if(str.compare(0, 9, "version 1")) {
		fprintf(stderr, "SMDLoader: ERROR: Unknown model format '%s'\n",str.c_str());
		return model;
	}
	while(!ifs.eof()){
		getline(ifs, str); transform (str.begin(),str.end(), str.begin(), ::tolower);
		if(str.compare(0, 9, "triangles")==0)
			model->setTriangles(loadTriangleBlock(ifs));
// 		fprintf(stderr, str.c_str());
	}
	return model;
}
